<template>
  <div class="bg-gray-50">
    <div class="container mx-auto p-6 flex gap-6 max-w-[100%]" style="padding: 10px; background-color: #fff">
      <!-- 左侧输入区 -->
      <div
        class="w-1/4 bg-white rounded-lg shadow-lg p-6"
        style="margin: auto"
        :style="{
          marginTop: words.length < 1 ? 'calc(50vh - 200px)' : '0',
          height: words.length < 1 ? 'auto' : '88vh'
        }"
      >
        <h2 class="text-2xl font-bold mb-6 text-gray-800">
          学习路径规划
          <el-button type="primary" @click="mainDialogVisible = true" link>查看我的课程</el-button>
          <el-button type="primary" @click="historyDialogVisible = true" link>推荐历史</el-button>
        </h2>
        <div class="space-y-6">
          <div>
            <label class="block text-sm font-medium text-gray-700 mb-2">技能兴趣</label>
            <el-select
              v-model="skills"
              multiple
              filterable
              allow-create
              default-first-option
              :reserve-keyword="false"
              placeholder="请输入技能兴趣"
              class="w-full"
            >
              <el-option v-for="item in skillOptions" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </div>

          <div>
            <label class="block text-sm font-medium text-gray-700 mb-2">目标岗位</label>
            <el-input v-model="targetJob" placeholder="请输入目标岗位" class="w-full" />
          </div>

          <div class="flex gap-4">
            <el-button
              :type="testP ? 'primary' : 'danger'"
              class="flex-1 !rounded-button whitespace-nowrap"
              @click="testPlan"
            >
              测试 : {{ testP ? "开启" : "关闭" }}
            </el-button>
            <el-button
              type="primary"
              class="flex-1 !rounded-button whitespace-nowrap"
              @click="generatePlan"
              :loading="loading"
            >
              开始规划
            </el-button>
            <el-button class="flex-1 !rounded-button whitespace-nowrap" @click="resetForm" :disabled="loading">
              重置
            </el-button>
          </div>
          <!-- 词云图 -->
          <div
            v-if="words.length > 0"
            id="wordCloud"
            class="w-full h-full"
            style="height: 550px; width: 100%; user-select: none"
            @click="generateWordCloud"
          ></div>
        </div>
      </div>

      <!-- 中间路线图 -->
      <transition name="slide-right">
        <div v-if="courseData" class="w-2/5 bg-white rounded-lg shadow-lg p-6" style="height: 88vh">
          <h2 class="text-2xl font-bold mb-6 text-gray-800">学习路线</h2>
          <!-- 修改中间路线图容器结构 -->
          <div id="mermaid" class="w-full h-[800px] overflow-auto" ref="mermaidRef"></div>
        </div>
      </transition>

      <!-- 右侧课程列表 -->
      <transition name="slide-right">
        <div
          v-if="courseData"
          class="w-1/3 bg-white rounded-lg shadow-lg p-6"
          style="height: 88vh; display: flex; flex-direction: column"
        >
          <h2 class="text-2xl font-bold mb-6 text-gray-800">推荐课程</h2>
          <div class="space-y-4 overflow-y-auto max-h-[800px] custom-scrollbar" v-if="courseData">
            <div
              v-for="course in courseData.courses"
              :key="course.course_id"
              class="p-4 border border-gray-200 rounded-lg hover:shadow-md transition-shadow cursor-pointer"
            >
              <div class="flex items-center justify-between mb-2">
                <el-checkbox v-model="selectedCourseIds" :label="course.course_id"></el-checkbox>
                <div class="flex space-x-1">
                  <el-tag :type="getStageType(course.stage)" size="small" style="margin-right: 10px">
                    第{{ course.stage }}阶段
                  </el-tag>
                  <el-tag :type="getStageType(course.nature)" size="small" style="margin-right: 10px">
                    {{ course.nature }}
                  </el-tag>
                  <el-tag :type="getStageType(course.assessment)" size="small" style="margin-right: 10px">
                    {{ course.assessment }}
                  </el-tag>
                </div>
              </div>
              <h3 class="text-lg font-medium text-gray-800 mb-2" @click="showCourseDetail(course)">
                {{ course.course_name }}
              </h3>
              <p class="text-sm text-gray-600 line-clamp-2">{{ course.recommend_reason }}</p>
            </div>
          </div>
          <div class="flex items-center justify-between mt-4" style="margin-top: 20px">
            <el-checkbox v-model="allSelected" @change="toggleAllSelection">全选</el-checkbox>
            <el-button
              type="primary"
              @click="goToSelectCourses"
              :disabled="selectedCourseIds.length === 0"
              style="margin-left: 10px; width: 90%"
              >去选课</el-button
            >
          </div>
        </div>
      </transition>
    </div>

    <!-- 课程详情弹窗 -->
    <el-dialog
      v-model="dialogVisible"
      :title="selectedCourse ? selectedCourse.course_name : '课程详情'"
      width="30%"
      align-center="true"
      center
      fontSize="26px"
    >
      <div v-if="selectedCourse">
        <div class="mb-4">
          <span class="text-gray-500">课程编号：</span>
          <span>{{ selectedCourse.course_id }}</span>
        </div>
        <div class="mb-4">
          <span class="text-gray-500">课程学分：</span>
          <span>{{ selectedCourse.credit }}</span>
        </div>
        <div class="mb-4">
          <span class="text-gray-500">推荐原因：</span>
          <span class="mt-2 text-gray-600">{{ selectedCourse.recommend_reason }}</span>
        </div>
        <div class="mb-4">
          <span class="text-gray-500">学习阶段：</span>
          <el-tag :type="getStageType(selectedCourse.stage)" class="ml-2"> 第{{ selectedCourse.stage }}阶段 </el-tag>
        </div>
        <div class="mb-4">
          <span class="text-gray-500">课程性质：</span>
          <el-tag :type="getStageType(selectedCourse.nature)" class="ml-2" size="small">
            {{ selectedCourse.nature }}
          </el-tag>
        </div>
        <div class="mb-4">
          <span class="text-gray-500">考核方式：</span>
          <el-tag :type="getStageType(selectedCourse.assessment)" class="ml-2" size="small">
            {{ selectedCourse.assessment }}
          </el-tag>
        </div>
        <div class="mb-4">
          <span class="text-gray-500">开课学院：</span>
          <el-tag :type="selectedCourse.dept" class="ml-2" size="small">
            {{ selectedCourse.dept }}
          </el-tag>
        </div>
        <div>
          <span class="text-gray-500">课程描述：</span>
          <span class="mt-2 text-gray-600">{{ selectedCourse.desc }}</span>
        </div>
      </div>
    </el-dialog>
  </div>
  <el-dialog v-model="mainDialogVisible" width="50%" center>
    <!-- 主对话框 -->
    <template #header>
      <div class="dialog-header">
        <span>个人信息</span>
        <el-button type="primary" @click="showUpdateDialog" :icon="Refresh" circle />
      </div>
    </template>

    <!-- 学期筛选 -->
    <div class="filter-container">
      <el-select v-model="selectedTerm" placeholder="请选择学期">
        <el-option label="全部学期" value="all" />
        <el-option v-for="term in uniqueTerms" :key="term" :label="term" :value="term" />
      </el-select>
    </div>

    <!-- 课程表格 -->
    <div class="table-container">
      <template v-for="(group, type) in filteredCourses" :key="type">
        <h3 class="group-title" v-if="group.length > 0">{{ typeMap[type] }}</h3>
        <el-table
          :data="group"
          stripe
          :row-class-name="tableRowClassName"
          :header-cell-style="{
            position: 'sticky',
            top: '40px',
            zIndex: '1',
            background: '#fff'
          }"
          v-if="group.length > 0"
        >
          <el-table-column prop="code" label="课程代码" width="120" sortable align="center" />
          <el-table-column prop="name" label="课程名称" align="center" />
          <el-table-column prop="time" label="学期" width="180" sortable align="center" />
          <el-table-column prop="grade" label="成绩" width="120" sortable align="center">
            <template #default="{ row }">
              <span :class="gradeClass(row.grade)">{{ row.grade }}</span>
            </template>
          </el-table-column>

          <template #empty>
            <div style="text-align: center; color: #999; margin-top: 100px">暂无数据</div>
          </template>
        </el-table>
      </template>
    </div>

    <!-- 更新对话框 -->
    <el-dialog v-model="updateDialogVisible" title="登录更新" width="30%" append-to-body center>
      <el-form :model="loginForm" ref="loginFormRef" style="padding: 0 20px">
        <el-form-item label="学号" prop="studentId">
          <el-input v-model="loginForm.studentId" autocomplete="off" :readonly="true" />
        </el-form-item>
        <el-form-item>
          <el-checkbox v-model="loginForm.hardUpdate">强制更新</el-checkbox>
          <el-checkbox v-model="loginForm.remember" v-if="loginForm.hardUpdate">记住密码</el-checkbox>
        </el-form-item>
        <el-form-item label="密码" prop="password" v-if="loginForm.hardUpdate">
          <el-input
            v-model="loginForm.password"
            type="password"
            show-password
            autocomplete="new-password"
            placeholder="MySeig系统密码"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="updateDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleUpdate">确认</el-button>
      </template>
    </el-dialog>
  </el-dialog>
  <el-dialog v-model="historyDialogVisible" width="40%" center>
    <div style="margin-bottom: 20px">
      <h2>推荐历史</h2>
    </div>
    <el-table
      :data="historyData"
      stripe
      :row-class-name="tableRowClassName"
      :header-cell-style="{
        position: 'sticky',
        top: '40px',
        zIndex: '1',
        background: '#fff'
      }"
      @row-click="historyHandleRowClick"
      :cell-style="{
        textAlign: 'center'
      }"
      :style="{
        // userSelect: 'none',
      }"
    >
      <el-table-column prop="updated_at" label="日期" align="center">
        <template #default="{ row }">
          {{ row.updated_at.replace("T", " ") }}
        </template>
      </el-table-column>
      <el-table-column prop="recommend_data.interests" label="技能兴趣" align="center">
        <template #default="{ row }">
          <div style="display: flex; flex-wrap: wrap; gap: 4px; justify-content: center">
            <el-tag
              v-for="(interest, index) in row.recommend_data?.interests || []"
              :key="index"
              size="large"
              effect="light"
              round
            >
              {{ interest }}
            </el-tag>
          </div>
        </template>
      </el-table-column>
      <el-table-column prop="recommend_data.career_goal" label="目标岗位" align="center" />
    </el-table>
  </el-dialog>
  <div v-if="isVisible" class="global-overlay">
    <div class="loader-content">
      <transition name="icon-swap" mode="out-in">
        <div v-if="isCompleted" key="success" class="success-check"></div>
        <div v-else key="loading" class="loader-spinner"></div>
      </transition>
      <transition name="text-fade" mode="out-in">
        <p :key="text" class="status-text">{{ text }}</p>
      </transition>
    </div>
  </div>
</template>
<script lang="ts" setup>
  import { ref, computed, onMounted, watch } from "vue";
  import mermaid from "mermaid";
  // @ts-ignore
  import WordCloud from "wordcloud";
  import { Refresh } from "@element-plus/icons-vue";
  import { encrypt, decrypt } from "../utils/crypto";
  import { ElMessage } from "element-plus";
  import "./output.css";
  import api from "../axios/api";

  const skills = ref<string[]>([]);
  const targetJob = ref("");
  const loading = ref(false);
  const dialogVisible = ref(false);
  const selectedCourse = ref();
  const mermaidRef = ref<HTMLElement | null>(null); // 修改类型
  const selectedCourseIds = ref<string[]>([]);
  const allSelected = ref(false);
  const testP = ref(true);
  const historyDialogVisible = ref(false);
  const historyData = ref([]); // 使用 ref 来存储数据

  const testPlan = () => {
    if (import.meta.env.VITE_HMR_MODE === "local") {
      testP.value = !testP.value;
    }
    // testP.value = !testP.value ////////////////////////////////////////////////////////////////////////////////////////////////////开关
    if (testP.value) {
      ElMessage.success("由于大模型api限制，功能暂不开放");
    } else {
      ElMessage.error("测试模式关闭");
    }
  };

  const skillOptions = [
    { value: "Python", label: "Python" },
    { value: "数据分析", label: "数据分析" },
    { value: "网络爬虫", label: "网络爬虫" },
    { value: "数据可视化", label: "数据可视化" },
    { value: "大数据", label: "大数据" }
  ];

  const courseData = ref();
  const words = ref<string[]>([]);

  const getStageType = (stage: string) => {
    if (["选修", "必修"].includes(stage)) {
      if (stage === "选修") {
        return "success";
      } else {
        return "primary";
      }
    }
    if (["考试", "考查"].includes(stage)) {
      if (stage === "考试") {
        return "primary";
      } else {
        return "success";
      }
    }
    const types = ["info", "warning", "danger"];
    return types[parseInt(stage) - 1] || "info";
  };

  const showCourseDetail = (course: any) => {
    console.log(course);
    selectedCourse.value = course;
    dialogVisible.value = true;
  };

  const getHistoryData = async () => {
    try {
      const response = await api.getAiRecommendHistory(localStorage.getItem("userId") || "");
      historyData.value = response.data; // 更新 ref 的值
      console.log(historyData.value);
    } catch (error) {
      console.error("获取推荐历史数据失败", error);
    }
  };

  const historyHandleRowClick = (row: any) => {
    console.log(row);
    skills.value = row.recommend_data.interests;
    targetJob.value = row.recommend_data.career_goal;
    words.value = row.recommend_data.select_worlds;
    setTimeout(() => {
      generateWordCloud();
    }, 500);
    courseData.value = row.recommend_data.result.result;
    setTimeout(() => {
      generateMermaid();
    }, 500);
    historyDialogVisible.value = false;
    addCourseInfo();
  };

  const generateMermaid = () => {
    // 等待0.5s
    setTimeout(() => {
      console.log(mermaidRef.value);
      if (mermaidRef.value) {
        // 清空容器并插入带 mermaid 类的代码
        mermaidRef.value.innerHTML = `<pre class="mermaid" style="width: 80%">${courseData.value.mermaid_code}</pre>`;

        // 使用 requestAnimationFrame 确保 DOM 更新后执行
        requestAnimationFrame(() => {
          // 直接调用 contentLoaded 重新渲染
          mermaid.contentLoaded();
          loading.value = false;
        });
      }
    }, 500);
  };

  // 修改 generatePlan 方法
  const generatePlan = async () => {
    loading.value = true;

    if (testP.value) {
      ElMessage.success("测试模式开启");
      skills.value = ["Python"];
      targetJob.value = "爬虫工程师";
    }

    // 获取输入的技能兴趣和目标岗位
    const interests = skills.value;
    const career_goal = targetJob.value;

    if (interests.length === 0 || career_goal === "") {
      ElMessage.error("请输入技能兴趣和目标岗位");
      loading.value = false;
      return;
    }

    setTimeout(async () => {
      await setWordData(interests, career_goal);
      generateWordCloud();
      setTimeout(async () => {
        await setCourseData(interests, career_goal);
        generateMermaid();
        addCourseInfo();
        loading.value = false;
      }, 1000);
    }, 1000);
  };
  const isVisible = ref(false); // 对话框是否可见
  const isCompleted = ref(false); // 是否完成
  const text = ref("");

  const complete = (message: string = "操作完成!"): Promise<void> => {
    return new Promise(resolve => {
      // 返回 Promise
      isCompleted.value = true;
      text.value = message;

      setTimeout(() => {
        isVisible.value = false;
        resolve();
      }, 3000);
    });
  };

  // 设置词云数据
  const setWordData = async (interests: string[], career_goal: string): Promise<void> => {
    isCompleted.value = false;
    let error_words = [
      "Python",
      "Scrapy",
      "HTTP协议",
      "XPath",
      "正则表达式",
      "反反爬虫",
      "Selenium",
      "分布式爬虫",
      "数据清洗",
      "BeautifulSoup",
      "Requests",
      "Asyncio",
      "Aiohttp",
      "代理IP",
      "MySQL",
      "MongoDB",
      "API接口",
      "Headless",
      "数据解析"
    ];
    if (testP.value) {
      words.value = error_words;
      return;
    }

    return new Promise(async (resolve, reject) => {
      try {
        isVisible.value = true;
        text.value = "获取核心词中...";
        let ws: WebSocket;
        const baseUrl = import.meta.env.VITE_API_BASE_URL.replace("http://", "ws://");
        const url = new URL(`${baseUrl}/api/course/ws/get_ai_worlds`);
        // 添加查询参数
        url.searchParams.append("career_goal", career_goal);
        interests.forEach(interest => {
          url.searchParams.append("interests", interest);
        });
        // 创建 WebSocket 连接
        ws = new WebSocket(url.toString());

        ws.onmessage = async event => {
          const message = event.data;
          if (message.includes("result")) {
            words.value = JSON.parse(message).result;
            ws.close();
            // loading.value = false;
            // 等待 complete 执行完毕（包括 3 秒隐藏动画）
            await complete("获取核心词成功, 消耗token：" + JSON.parse(message).total_tokens);
            resolve();
          } else {
            text.value = message;
          }
        };

        ws.onerror = error => {
          reject(error);
          ElMessage.error("获取核心词失败");
          words.value = error_words;
        };

        ws.onclose = event => {
          if (event.wasClean) {
            console.log("连接正常关闭");
          } else {
            console.error("连接意外断开，可能由于网络问题");
            ElMessage.error("连接中断，请重试");
          }
        };
      } catch (error) {
        reject(error);
        ElMessage.error("获取核心词失败");
        words.value = error_words;

        await complete("获取核心词失败");
      }
    });
  };

  // 设置课程数据
  const setCourseData = async (interests: string[], career_goal: string): Promise<void> => {
    isCompleted.value = false;
    let error_courses = {
      courses: [
        {
          course_id: "NN0072",
          course_name: "Python网络爬虫技术",
          recommend_reason: "直接对应爬虫工程师岗位需求，强化Python网络爬虫技能",
          stage: "1"
        },
        {
          course_id: "SK2004",
          course_name: "Python数据预处理",
          recommend_reason: "提升数据处理能力，为爬虫工程师岗位提供数据支持",
          stage: "1"
        },
        {
          course_id: "SK2101",
          course_name: "数据处理与应用项目实训",
          recommend_reason: "通过项目实战，提升Python在数据处理和应用开发中的实践能力",
          stage: "2"
        },
        {
          course_id: "ND2009",
          course_name: "数据分析与数据可视化",
          recommend_reason: "增强数据分析和可视化能力，为爬虫工程师提供数据展示支持",
          stage: "2"
        },
        {
          course_id: "SK3010",
          course_name: "大数据处理引擎与实践",
          recommend_reason: "掌握大数据处理技术，为处理大规模爬虫数据提供技术支持",
          stage: "3"
        }
      ],
      mermaid_code: `
        flowchart TD
          subgraph WindCheck第一阶段
          A[Python网络爬虫技术]
          B[Python数据预处理]
          end
          subgraph WindCheck第二阶段
          C[数据处理与应用项目实训]
          D[数据分析与数据可视化]
          end
          subgraph WindCheck第三阶段
          E[大数据处理引擎与实践]
          end
          A --> C
          B --> C
          C --> D
          D --> E
        `
    };
    if (testP.value) {
      courseData.value = error_courses;
      addCourseInfo();
      return;
    }
    //////////////////////////////////////////////////////////////////////////

    return new Promise(async (resolve, reject) => {
      try {
        isVisible.value = true;
        text.value = "获取推荐课程中...";
        let ws: WebSocket;
        const baseUrl = import.meta.env.VITE_API_BASE_URL.replace("http://", "ws://");
        const url = new URL(`${baseUrl}/api/course/ws/get_ai_courses`);
        // 添加查询参数
        url.searchParams.append("career_goal", career_goal);
        interests.forEach(interest => {
          url.searchParams.append("interests", interest);
        });
        url.searchParams.append("user_id", localStorage.getItem("userId") || "");
        words.value.forEach(words => {
          url.searchParams.append("select_worlds", words);
        });
        // 创建 WebSocket 连接
        ws = new WebSocket(url.toString());

        ws.onmessage = async event => {
          const message = event.data;
          if (message.includes("result")) {
            courseData.value = JSON.parse(message).result;
            ws.close();
            await complete("获取推荐课程数据成功, 消耗token：" + JSON.parse(message).total_tokens);
            resolve();
          } else {
            text.value = message;
          }
        };

        ws.onerror = error => {
          reject(error);
          ElMessage.error("获取核心词失败");
          courseData.value = error_courses;
        };

        ws.onclose = event => {
          if (event.wasClean) {
            console.log("连接正常关闭");
          } else {
            console.error("连接意外断开，可能由于网络问题");
            ElMessage.error("连接中断，请重试");
          }
        };
      } catch (error) {
        reject(error);
        ElMessage.error("获取核心词失败");
        courseData.value = error_courses;
        await complete("获取推荐课程数据失败");
      }
    });

    // try {
    //   const aiSelectedCourses = await api.getAiSelectedCourses(
    //     interests,
    //     career_goal,
    //     localStorage.getItem("userId") || "",
    //     words.value
    //   );
    //   console.log(aiSelectedCourses.data);
    //   courseData.value = aiSelectedCourses.data.result;
    //   ElMessage.success({
    //     message: "获取推荐课程数据成功, 消耗token：" + aiSelectedCourses.data.total_tokens,
    //     duration: 5000
    //   });
    // } catch (error) {
    //   ElMessage.error("获取推荐课程数据失败");
    //   courseData.value = error_courses;
    // }
    // courseData.value.courses增加一个字段，desc，从localstorage中获取course_data，在其Courses列表内。搜索Code为course_id的课程，将其Sim.Desc字段赋值给desc
  };

  const addCourseInfo = () => {
    courseData.value.courses.forEach((course: any) => {
      const allCourseData = localStorage.getItem("course_data");
      if (allCourseData) {
        const courses = JSON.parse(allCourseData).Courses;
        const courseData = courses.find((item: any) => item.Code === course.course_id);
        course.desc = courseData.Sim.Desc;
        course.nature = courseData.Nature;
        course.dept = courseData.Dept;
        course.credit = courseData.Crd;
        //考核方式
        course.assessment = courseData.Sim.Assess;
      }
    });
    console.log(courseData.value);
  };
  // 修改 resetForm 方法
  const resetForm = () => {
    skills.value = [];
    targetJob.value = "";
    if (mermaidRef.value) {
      // 彻底清空容器内容
      mermaidRef.value.innerHTML = "";
    }
    courseData.value = null;
    words.value = [];
    // 清空词云图
    WordCloud(document.getElementById("wordCloud"), {
      list: []
    });
  };

  const generateWordCloud = () => {
    // 生成词云图
    WordCloud(document.getElementById("wordCloud"), {
      list: words.value.map((word: string) => [word, Math.floor(Math.random() * 3) + 1]), // 权重随机为1或2
      gridSize: 12, // 网格大小
      weightFactor: 20, // 权重因子
      color: "random-dark", // 颜色改为深色
      backgroundColor: "#fff", // 背景颜色
      rotateRatio: 0, // 旋转比例
      fontFamily: "微软雅黑",
      fontWeight: "bold",
      //字体大小范围
      fontSize: [10, 20],
      // 长方形
      shape: "rect"
    });
  };

  const goToSelectCourses = () => {
    console.log("选中的课程代码:", selectedCourseIds.value);
    // 这里可以添加进一步的逻辑，比如跳转到选课页面等
    localStorage.setItem("selectedCourseIds", JSON.stringify(selectedCourseIds.value));
    window.open("./course", "_blank");
  };

  const toggleAllSelection = () => {
    if (allSelected.value) {
      selectedCourseIds.value = courseData.value.courses.map((course: any) => course.course_id);
    } else {
      selectedCourseIds.value = [];
    }
  };

  // 初始数据
  const rawData = ref();

  // 设置个人课程数据
  const setPersonalCourseData = async () => {
    if (loginForm.value.hardUpdate && !loginForm.value.password) {
      ElMessage.error("请输入密码");
      return;
    }
    rawData.value = JSON.parse(localStorage.getItem("personal_course_data") || "{}");
    if (JSON.stringify(rawData.value) === "{}") {
      try {
        const response = await api.getPersonalCourseData(
          localStorage.getItem("userId"),
          loginForm.value.studentId,
          loginForm.value.password,
          loginForm.value.hardUpdate
        );
        console.log(response.data);
        rawData.value = response.data;
        localStorage.setItem("personal_course_data", JSON.stringify(rawData.value));
        ElMessage.success("获取个人课程数据成功");
        updateDialogVisible.value = false;

        if (loginForm.value.remember && loginForm.value.password) {
          localStorage.setItem("studentId", loginForm.value.studentId);
          localStorage.setItem("studentPw", encrypt(loginForm.value.password));
          localStorage.setItem("rememberMe", loginForm.value.remember.toString());
        }
      } catch (error) {
        mainDialogVisible.value = true;
        updateDialogVisible.value = true;
        loginForm.value.hardUpdate = true;
      }
    }
  };

  // 类型映射
  const typeMap: Record<string, string> = {
    bixiu: "必修课程",
    xuanxiu: "选修课程",
    zxianxuan: "专项选修"
  };

  // 对话框状态
  const mainDialogVisible = ref(false);
  const updateDialogVisible = ref(false);
  const selectedTerm = ref("all");

  // 登录表单
  const loginForm = ref({
    studentId: localStorage.getItem("studentId") || "",
    password: "",
    remember: localStorage.getItem("rememberMe") === "true",
    hardUpdate: false
  });

  // 处理成绩颜色
  const gradeClass = (grade: string) => {
    const scoreMap = {
      优: "grade-excellent",
      良: "grade-good",
      中: "grade-medium",
      及格: "grade-pass",
      不及格: "grade-fail"
    };

    // 如果成绩是数字，进行比较
    if (!isNaN(Number(grade))) {
      const numericGrade = Number(grade);
      if (numericGrade >= 90) return "grade-excellent";
      if (numericGrade >= 80) return "grade-good";
      // if (numericGrade >= 70) return 'grade-medium'
      if (numericGrade >= 60) return "grade-medium";
      return "grade-fail";
    } else if (grade.includes("补")) return "grade-fail";
    else if (grade === "在读") return "grade-excellent";
    else if (grade === "未修") return "grade-medium";
    return scoreMap[grade as keyof typeof scoreMap] || "";
  };

  // 获取唯一学期列表
  const uniqueTerms = computed(() => {
    const terms = new Set();
    // 如果rawData.value为空，则返回空数组
    if (rawData.value === undefined) {
      return [];
    }
    Object.values(rawData.value).forEach((courses: any) => {
      if (Array.isArray(courses)) {
        courses.forEach((c: any) => terms.add(c.time));
      }
    });
    return Array.from(terms).sort();
  });

  // 过滤后的课程数据
  const filteredCourses = computed(() => {
    const result: any = {};
    // 如果rawData.value为空，则返回空对象
    if (rawData.value === undefined) {
      return {};
    }
    Object.entries(rawData.value).forEach(([type, courses]: any) => {
      if (type !== "parse_crd") {
        result[type] = courses.filter((c: any) => selectedTerm.value === "all" || c.time === selectedTerm.value);
      }
    });
    return result;
  });

  // 表格行样式
  const tableRowClassName = ({ rowIndex }: any) => {
    return rowIndex % 2 === 0 ? "even-row" : "odd-row";
  };

  // 显示更新对话框
  const showUpdateDialog = () => {
    // 读取保存的登录信息
    if (localStorage.getItem("rememberMe") === "true") {
      loginForm.value = {
        studentId: localStorage.getItem("studentId") || "",
        password: localStorage.getItem("studentPw") ? decrypt(localStorage.getItem("studentPw") || "") : "",
        remember: localStorage.getItem("rememberMe") === "true",
        hardUpdate: false
      };
    }
    updateDialogVisible.value = true;
    console.log(loginForm.value);
  };

  // 处理数据更新
  const handleUpdate = () => {
    console.log(loginForm.value);
    localStorage.removeItem("personal_course_data");
    if (loginForm.value.remember && loginForm.value.password) {
      localStorage.setItem("studentPw", encrypt(loginForm.value.password));
      localStorage.setItem("rememberMe", "true");
    } else {
      localStorage.removeItem("studentPw");
      localStorage.removeItem("rememberMe");
    }
    setPersonalCourseData();
  };

  // 监听 historyDialogVisible 的变化
  watch(historyDialogVisible, newVal => {
    if (newVal) {
      getHistoryData(); // 当对话框打开时获取数据
    }
  });

  onMounted(() => {
    mermaid.initialize({
      startOnLoad: true,
      theme: "default",
      securityLevel: "loose"
    });
    setPersonalCourseData();
  });
</script>

<style scoped>
  .el-select {
    width: 100%;
  }

  .el-dialog {
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    margin: 0px !important;
  }

  .shadow-lg {
    --tw-shadow: none !important;
  }

  .custom-scrollbar {
    /* 隐藏滚动条 */

    -ms-overflow-style: auto; /* IE 和 Edge */
    scrollbar-width: auto; /* Firefox */

    &::-webkit-scrollbar {
      display: block; /* Chrome, Safari 和 Opera */
      width: 2px;
    }
    &::-webkit-scrollbar-thumb {
      background-color: #ccc;
    }
  }

  /* 确保 mermaid 生成的 SVG 居中 */
  #mermaid {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100%; /* 确保容器高度 */
  }

  /* 左侧滑入动画 */
  .slide-left-enter-active,
  .slide-left-leave-active {
    transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .slide-left-enter-from {
    opacity: 0;
    transform: translateX(-20px);
  }

  .slide-left-leave-to {
    opacity: 0;
    transform: translateX(20px);
  }

  /* 右侧滑入动画 */
  .slide-right-enter-active,
  .slide-right-leave-active {
    transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .slide-right-enter-from {
    opacity: 0;
    transform: translateX(20px);
  }

  .slide-right-leave-to {
    opacity: 0;
    transform: translateX(-20px);
  }

  /* 弹窗 */
  .dialog-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .group-title {
    position: sticky;
    top: 0;
    background: #fff;
    z-index: 2;
    margin: 0;
    padding: 10px 0;
    color: #409eff;
  }

  .table-container {
    max-height: 60vh;
    overflow-y: auto;
    /* 禁止选中 */
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }

  .grade-excellent {
    color: #67c23a;
  }
  .grade-good {
    color: #e6a23c;
  }
  .grade-medium {
    color: #909399;
  }
  .grade-pass {
    color: #409eff;
  }
  .grade-fail {
    color: #f56c6c;
  }

  .even-row {
    background-color: #fafafa;
  }
  .odd-row {
    background-color: #fff;
  }

  .filter-container {
    margin-bottom: 20px;
  }

  .table-container {
    max-height: 60vh;
    overflow-y: auto;
  }

  .el-table {
    margin-bottom: 20px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    border-radius: 8px;
  }

  .el-dialog__body {
    padding: 20px;
  }

  .el-button {
    transition: all 0.3s;
  }
  .global-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 9999;
  }

  .loader-content {
    background: white;
    padding: 40px;
    border-radius: 12px;
    text-align: center;
    width: 280px; /* 固定宽度 */
    height: 180px;
    max-width: 90%; /* 可选：防止在小屏幕溢出 */
    position: relative;
  }

  /* 加载动画 */
  .loader-spinner {
    display: inline-block;
    width: 48px;
    height: 48px;
    border: 4px solid #f3f3f3;
    border-radius: 50%;
    border-top-color: #3498db;
    animation: spin 1s linear infinite;
    margin-bottom: 20px;
  }

  /* 修正后的成功图标 */
  .success-check {
    width: 48px;
    height: 48px;
    margin: 0 auto 20px;
    position: relative;
  }

  .success-check::before {
    content: "";
    position: absolute;
    left: 14px; /* 调整定位 */
    top: 22px; /* 调整定位 */
    width: 24px;
    height: 12px;
    border: solid 3px #4caf50;
    border-top: none;
    border-right: none;
    transform: rotate(-45deg) scale(1);
    animation: checkAnim 0.6s ease-out forwards;
  }

  /* 关键帧动画 */
  @keyframes spin {
    to {
      transform: rotate(360deg);
    }
  }

  @keyframes checkAnim {
    0% {
      opacity: 0;
      transform: rotate(-45deg) scale(0);
    }
    50% {
      opacity: 1;
      transform: rotate(-45deg) scale(1.1);
    }
    100% {
      opacity: 1;
      transform: rotate(-45deg) scale(1);
    }
  }

  /* 过渡动画 */
  .icon-swap-enter-active,
  .icon-swap-leave-active {
    transition: all 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55);
  }

  .icon-swap-enter-from {
    opacity: 0;
    transform: scale(0.7);
  }

  .icon-swap-leave-to {
    opacity: 0;
    transform: scale(1.3);
  }

  .status-text {
    font-size: 16px;
    color: #333;
    margin: 0;
    min-height: 24px;
  }

  .text-fade-enter-active,
  .text-fade-leave-active {
    transition: all 0.3s ease;
  }

  .text-fade-enter-from {
    opacity: 0;
    transform: translateY(-8px);
  }

  .text-fade-leave-to {
    opacity: 0;
    transform: translateY(8px);
  }
</style>
